package state.socket;

import particle.core.network.ISocketConnectEventHandler;
import particle.core.network.ISocketDataReceiveEventHandler;
import particle.core.network.ISocketStatusEventHandler;
import particle.core.network.SocketBase;
import particle.core.network.SocketConnectEvent;
import particle.core.network.SocketDataReceiveEvent;
import particle.core.network.SocketStatusEvent;
import particle.core.tools.ByteBuffer;
import state.GameControl;
import state.util.SerialUtil;
import state.util.array.ByteArray;

public class ReaderThread extends GameControl implements ISocketDataReceiveEventHandler, ISocketConnectEventHandler, ISocketStatusEventHandler {
  private int lastTimeReveive = 0;
  private boolean isRunning = true;
  private DataReceiveListener listener = null;
  private ClientConnection client = null;
  private ByteBuffer inputStream = null;

  public ReaderThread(ByteBuffer is1, DataReceiveListener listener1, ClientConnection client1) {
    this.inputStream = is1;
    this.listener = listener1;
    this.client = client1;
    setTimeInterval(20);
    setRepeat(true);
    start();
  }
  
  public void perform() {
    if (isRunning) {
      if (inputStream.getLength() < 4) {
        return;
      }
      
      int len = readInt();
      if (len < 0 || len > 1000000000) {
        System.out.println("ReaderThread: len is not valid: " + len);
        inputStream.remove(0, 4);
        return;
      }
      
      if (inputStream.getLength() < len + 4) {
        return;
      }
      
      ByteArray allData = new ByteArray(inputStream.getBuffer(), inputStream.getLength());
      ByteArray data = ByteArray.create(len);
      ByteArray.arraycopy(allData, 4, data, 0, len);
      inputStream.remove(0, len + 4);
      lastTimeReveive = (int) System.currentTimeMillis();
      listener.onRecieveData(DataPackage.createDataPackage(data));
    }
  }

  public void onSocketDataReceive(SocketBase socket, SocketDataReceiveEvent event1) {
  }

  private int readInt() {
    byte[] byteArray = new byte[4];
    for (int i = 0; i < 4; i++) {
      byteArray[i] = inputStream.getByte(i);
    }
    return SerialUtil.deserialToInt(new ByteArray(byteArray, 4));
  }

  public void onSocketStatus(SocketBase socket, SocketStatusEvent event1) {
    if (event1.status == SocketStatusEvent.StatusConnectionClosed) {
      System.out.println(">>>>>Socket close by remoted server");
      if (listener != null) {
        listener.onConnectFail();
      }
    } else if (event1.status == SocketStatusEvent.StatusConnectionTimeout) {
      System.out.println(">>>>>Socket timeout");
      if (listener != null) {
        listener.onConnectFail();
      }
    }
    detroy();
  }

  public void onSocketConnect(SocketBase socket, SocketConnectEvent event1) {
    client.isConnectSuccess = true;
    if (listener != null) {
      listener.onConnectDone();
    }
  }

  public int getLastTimeReveive() {
    return lastTimeReveive;
  }

  public void detroy() {
    isRunning = false;
    if (inputStream != null) {
      inputStream.clear();
      inputStream = null;
    }
    listener = null;
  }
}
